<template>
  <div class="rich-text-editor">
    <div class="editor-toolbar">
      <div class="toolbar-group">
        <el-button-group>
          <el-button
            :type="isActive('bold') ? 'primary' : 'default'"
            size="small"
            @click="execCommand('bold')"
            title="粗体"
          >
            <strong>B</strong>
          </el-button>
          <el-button
            :type="isActive('italic') ? 'primary' : 'default'"
            size="small"
            @click="execCommand('italic')"
            title="斜体"
          >
            <em>I</em>
          </el-button>
          <el-button
            :type="isActive('underline') ? 'primary' : 'default'"
            size="small"
            @click="execCommand('underline')"
            title="下划线"
          >
            <u>U</u>
          </el-button>
        </el-button-group>
      </div>

      <div class="toolbar-group">
        <el-select
          v-model="fontSize"
          size="small"
          style="width: 80px"
          @change="changeFontSize"
        >
          <el-option label="12px" value="12px" />
          <el-option label="14px" value="14px" />
          <el-option label="16px" value="16px" />
          <el-option label="18px" value="18px" />
          <el-option label="20px" value="20px" />
          <el-option label="24px" value="24px" />
          <el-option label="28px" value="28px" />
          <el-option label="32px" value="32px" />
        </el-select>

        <el-select
          v-model="fontFamily"
          size="small"
          style="width: 120px"
          @change="changeFontFamily"
        >
          <el-option label="默认字体" value="" />
          <el-option label="宋体" value="SimSun" />
          <el-option label="黑体" value="SimHei" />
          <el-option label="微软雅黑" value="Microsoft YaHei" />
          <el-option label="Arial" value="Arial" />
          <el-option label="Times New Roman" value="Times New Roman" />
        </el-select>
      </div>

      <div class="toolbar-group">
        <el-button-group>
          <el-button
            :type="isActive('justifyLeft') ? 'primary' : 'default'"
            size="small"
            @click="execCommand('justifyLeft')"
            title="左对齐"
          >
            左
          </el-button>
          <el-button
            :type="isActive('justifyCenter') ? 'primary' : 'default'"
            size="small"
            @click="execCommand('justifyCenter')"
            title="居中"
          >
            中
          </el-button>
          <el-button
            :type="isActive('justifyRight') ? 'primary' : 'default'"
            size="small"
            @click="execCommand('justifyRight')"
            title="右对齐"
          >
            右
          </el-button>
          <el-button
            :type="isActive('justifyFull') ? 'primary' : 'default'"
            size="small"
            @click="execCommand('justifyFull')"
            title="两端对齐"
          >
            ≡
          </el-button>
        </el-button-group>
      </div>

      <div class="toolbar-group">
        <el-button-group>
          <el-button
            :type="isActive('insertUnorderedList') ? 'primary' : 'default'"
            size="small"
            @click="execCommand('insertUnorderedList')"
            title="无序列表"
          >
            •
          </el-button>
          <el-button
            :type="isActive('insertOrderedList') ? 'primary' : 'default'"
            size="small"
            @click="execCommand('insertOrderedList')"
            title="有序列表"
          >
            1.
          </el-button>
        </el-button-group>
      </div>

      <div class="toolbar-group">
        <el-button-group>
          <el-button size="small" @click="insertLink" title="插入链接">
            链
          </el-button>
          <el-button size="small" @click="insertImage" title="插入图片">
            图
          </el-button>
          <el-button size="small" @click="triggerImageUpload" title="上传图片">
            上传图
          </el-button>
          <el-button size="small" @click="insertVideo" title="插入视频地址">
            视频址
          </el-button>
          <el-button size="small" @click="triggerVideoUpload" title="上传视频">
            上传视频
          </el-button>
          <el-button size="small" @click="triggerFileUpload" title="上传附件">
            附件
          </el-button>
          <el-button size="small" @click="insertTable" title="插入表格">
            表
          </el-button>
          <el-button
            size="small"
            @click="resizeSelectedImage"
            title="调整选中图片大小"
          >
            调图
          </el-button>
        </el-button-group>
      </div>

      <div class="toolbar-group">
        <span style="font-size: 12px; color: #666; margin-right: 6px"
          >文字颜色</span
        >
        <el-color-picker
          size="small"
          v-model="fontColor"
          @change="applyFontColor"
        />
        <span style="font-size: 12px; color: #666; margin: 0 6px 0 12px"
          >背景</span
        >
        <el-color-picker
          size="small"
          v-model="bgColor"
          @change="applyBgColor"
        />
      </div>

      <div class="toolbar-group">
        <el-button size="small" @click="clearFormat" title="清除格式">
          清
        </el-button>
        <el-button size="small" @click="undo" title="撤销"> ↶ </el-button>
        <el-button size="small" @click="redo" title="重做"> ↷ </el-button>
      </div>
    </div>

    <div
      ref="editorRef"
      class="editor-content"
      contenteditable="true"
      @input="handleInput"
      @keydown="handleKeydown"
      @paste="handlePaste"
      @focus="handleFocus"
      @blur="handleBlur"
      @click="handleImageClick"
    ></div>

    <!-- 隐藏文件选择器 -->
    <input
      ref="imageInputRef"
      type="file"
      accept="image/*"
      style="display: none"
      @change="onImageSelected"
    />
    <input
      ref="fileInputRef"
      type="file"
      style="display: none"
      @change="onFileSelected"
    />
    <input
      ref="videoInputRef"
      type="file"
      accept="video/*"
      style="display: none"
      @change="onVideoSelected"
    />
  </div>

  <!-- 插入链接对话框 -->
  <el-dialog v-model="showLinkDialog" title="插入链接" width="420px">
    <el-input
      v-model="linkUrl"
      placeholder="请输入链接地址，如 https://example.com"
    />
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="showLinkDialog = false">取消</el-button>
        <el-button type="primary" @click="confirmInsertLink">确定</el-button>
      </span>
    </template>
  </el-dialog>

  <!-- 插入图片地址对话框 -->
  <el-dialog v-model="showImageUrlDialog" title="插入图片地址" width="420px">
    <el-input
      v-model="imageUrl"
      placeholder="请输入图片地址，如 https://.../image.jpg"
    />
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="showImageUrlDialog = false">取消</el-button>
        <el-button type="primary" @click="confirmInsertImage">确定</el-button>
      </span>
    </template>
  </el-dialog>

  <!-- 插入视频地址对话框 -->
  <el-dialog v-model="showVideoUrlDialog" title="插入视频地址" width="520px">
    <el-input
      v-model="videoUrl"
      placeholder="请输入视频地址，如 https://.../video.mp4"
    />
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="showVideoUrlDialog = false">取消</el-button>
        <el-button type="primary" @click="confirmInsertVideoByUrl"
          >确定</el-button
        >
      </span>
    </template>
  </el-dialog>

  <!-- 插入表格对话框 -->
  <el-dialog v-model="showTableDialog" title="插入表格" width="420px">
    <div style="display: flex; gap: 12px">
      <el-input
        v-model.number="tableRows"
        type="number"
        min="1"
        placeholder="行数"
      />
      <el-input
        v-model.number="tableCols"
        type="number"
        min="1"
        placeholder="列数"
      />
    </div>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="showTableDialog = false">取消</el-button>
        <el-button type="primary" @click="confirmInsertTable">确定</el-button>
      </span>
    </template>
  </el-dialog>
</template>

<script>
import { ref, onMounted, watch, nextTick } from "vue";
import { ElMessage } from "element-plus";
import config from "@/config";

export default {
  name: "RichTextEditor",
  props: {
    modelValue: {
      type: String,
      default: "",
    },
    placeholder: {
      type: String,
      default: "请输入内容...",
    },
    height: {
      type: String,
      default: "300px",
    },
    isRoster: {
      type: Boolean,
      default: false,
    },
  },
  emits: ["update:modelValue", "change"],
  setup(props, { emit }) {
    const editorRef = ref(null);
    const fontSize = ref("16px");
    const fontFamily = ref("");
    const isFocused = ref(false);
    const imageInputRef = ref(null);
    const fileInputRef = ref(null);
    const videoInputRef = ref(null);

    // 对话框状态
    const showLinkDialog = ref(false);
    const linkUrl = ref("");
    const showImageUrlDialog = ref(false);
    const imageUrl = ref("");
    const showVideoUrlDialog = ref(false);
    const videoUrl = ref("");
    const showTableDialog = ref(false);
    const tableRows = ref(3);
    const tableCols = ref(3);

    // 颜色
    const fontColor = ref("");
    const bgColor = ref("");
    const savedRange = ref(null);

    // 选区保存/恢复
    const saveSelection = () => {
      const sel = window.getSelection();
      if (!sel || sel.rangeCount === 0) return;
      const range = sel.getRangeAt(0);
      if (
        editorRef.value &&
        editorRef.value.contains(range.commonAncestorContainer)
      ) {
        savedRange.value = range;
      }
    };
    const restoreSelection = () => {
      if (!savedRange.value) return;
      const sel = window.getSelection();
      sel.removeAllRanges();
      sel.addRange(savedRange.value);
    };

    // 初始化编辑器
    const initEditor = () => {
      if (editorRef.value) {
        editorRef.value.innerHTML = props.modelValue || "";
        editorRef.value.style.minHeight = props.height;
        editorRef.value.style.fontSize = fontSize.value;
        if (fontFamily.value) {
          editorRef.value.style.fontFamily = fontFamily.value;
        }
      }
    };

    // 执行命令
    const execCommand = (command, value = null) => {
      document.execCommand(command, false, value);
      editorRef.value.focus();
      updateModelValue();
    };

    // 检查命令是否激活
    const isActive = (command) => {
      return document.queryCommandState(command);
    };

    // 改变字体大小
    const changeFontSize = (size) => {
      if (!size) return;
      restoreSelection();
      if (savedRange.value) {
        const selection = window.getSelection();
        if (selection.rangeCount > 0) {
          const range = selection.getRangeAt(0);
          // 如果选区是空的，则创建一个空的文本节点以应用样式
          if (range.collapsed) {
            const span = document.createElement("span");
            span.style.fontSize = size;
            // 插入一个零宽空格以便光标可以定位
            span.innerHTML = "&#8203;";
            range.insertNode(span);
            // 将光标移到新创建的 span 内部
            range.setStart(span.firstChild, 1);
            range.collapse(true);
            selection.removeAllRanges();
            selection.addRange(range);
          } else {
            // 对于有内容的选区，使用 execCommand 插入 span
            const span = document.createElement("span");
            span.style.fontSize = size;
            try {
              range.surroundContents(span);
            } catch (e) {
              // 如果选区跨越了多个块级元素，surroundContents 会失败
              // 此时回退到 execCommand，但效果可能不理想
              console.warn(
                "surroundContents failed, falling back to styleWithCSS and fontSize command.",
                e
              );
              document.execCommand("styleWithCSS", false, true);
              document.execCommand("fontSize", false, "1"); // 用一个虚拟值
              const fontElements =
                editorRef.value.querySelectorAll('font[size="1"]');
              fontElements.forEach((el) => {
                el.style.fontSize = size;
                el.removeAttribute("size");
                // 将 font 标签替换为 span
                const parent = el.parentNode;
                while (el.firstChild) {
                  parent.insertBefore(el.firstChild, el);
                }
                parent.removeChild(el);
              });
            }
          }
        }
      }
      editorRef.value.focus();
      updateModelValue();
    };

    // 改变字体
    const changeFontFamily = (family) => {
      if (!family) return;
      restoreSelection();
      if (savedRange.value) {
        const selection = window.getSelection();
        if (selection.rangeCount > 0) {
          const range = selection.getRangeAt(0);
          if (range.collapsed) {
            const span = document.createElement("span");
            span.style.fontFamily = family;
            span.innerHTML = "&#8203;";
            range.insertNode(span);
            range.setStart(span.firstChild, 1);
            range.collapse(true);
            selection.removeAllRanges();
            selection.addRange(range);
          } else {
            const span = document.createElement("span");
            span.style.fontFamily = family;
            try {
              range.surroundContents(span);
            } catch (e) {
              console.warn(
                "surroundContents failed, falling back to styleWithCSS and fontName command.",
                e
              );
              document.execCommand("styleWithCSS", false, true);
              document.execCommand("fontName", false, "font-name-placeholder"); // Use a placeholder
              const fontElements = editorRef.value.querySelectorAll(
                'font[face="font-name-placeholder"]'
              );
              fontElements.forEach((el) => {
                el.style.fontFamily = family;
                el.removeAttribute("face");
                const parent = el.parentNode;
                while (el.firstChild) {
                  parent.insertBefore(el.firstChild, el);
                }
                parent.removeChild(el);
              });
            }
          }
        }
      }
      editorRef.value.focus();
      updateModelValue();
    };

    // 插入链接
    const insertLink = () => {
      linkUrl.value = "";
      showLinkDialog.value = true;
    };
    const confirmInsertLink = () => {
      const url = (linkUrl.value || "").trim();
      if (!url) return (showLinkDialog.value = false);
      execCommand("createLink", url);
      showLinkDialog.value = false;
    };

    // 插入图片
    const insertImage = () => {
      imageUrl.value = "";
      showImageUrlDialog.value = true;
    };
    const confirmInsertImage = () => {
      const url = (imageUrl.value || "").trim();
      if (!url) return (showImageUrlDialog.value = false);
      // 插入可调整大小的图片
      // 如果是展商名录页面，图片宽度为 185px高度为 110px
      let imageHtml = "";
      if (props.isRoster) {
        imageHtml = `<img src="${url}" style="width: 185px; height: 110px;" class="resizable-image" draggable="true" />`;
      } else {
        imageHtml = `<img src="${url}" style="max-width: 400px; height: auto;" class="resizable-image" draggable="true" />`;
      }
      execCommand("insertHTML", imageHtml);
      showImageUrlDialog.value = false;
    };

    // 触发上传图片
    const triggerImageUpload = () => {
      if (imageInputRef.value) imageInputRef.value.value = "";
      imageInputRef.value?.click();
    };

    // 触发上传附件
    const triggerFileUpload = () => {
      if (fileInputRef.value) fileInputRef.value.value = "";
      fileInputRef.value?.click();
    };

    // 视频: 触发上传
    const triggerVideoUpload = () => {
      if (videoInputRef.value) videoInputRef.value.value = "";
      videoInputRef.value?.click();
    };

    // 选择图片后上传
    const onImageSelected = async (e) => {
      const file = e.target.files && e.target.files[0];
      if (!file) return;
      try {
        const apiConfig = config.getApiConfig();
        const form = new FormData();
        form.append("file", file);
        form.append("type", "image");
        const resp = await fetch(`${apiConfig.baseURL}/api/upload/image`, {
          method: "POST",
          headers: {
            token: localStorage.getItem("adminToken") || "",
          },
          body: form,
        });
        const data = await resp.json();
        if (
          data &&
          (data.code === "200" || data.code === 200) &&
          data.data &&
          data.data.url
        ) {
          // 插入可调整大小的图片
          // 如果是展商名录页面，图片宽度为 185px高度为 110px
          let imageHtml = "";
          if (props.isRoster) {
            imageHtml = `<img src="${data.data.url}" style="width: 185px; height: 110px;" class="resizable-image" draggable="true" />`;
          } else {
            imageHtml = `<img src="${data.data.url}" style="max-width: 400px; height: auto;" class="resizable-image" draggable="true" />`;
          }
          // const imageHtml = `<img src="${data.data.url}" style="max-width: 400px; height: auto;" class="resizable-image" draggable="true" />`;
          execCommand("insertHTML", imageHtml);
          ElMessage.success("图片已插入");
        } else {
          ElMessage.error(data?.message || "上传图片失败");
        }
      } catch (err) {
        ElMessage.error("上传图片失败");
      } finally {
        if (imageInputRef.value) imageInputRef.value.value = "";
      }
    };

    // 选择附件后上传
    const onFileSelected = async (e) => {
      const file = e.target.files && e.target.files[0];
      if (!file) return;
      try {
        const apiConfig = config.getApiConfig();
        const form = new FormData();
        form.append("file", file);
        form.append("type", "file");
        const resp = await fetch(`${apiConfig.baseURL}/api/upload/file`, {
          method: "POST",
          headers: {
            token: localStorage.getItem("adminToken") || "",
          },
          body: form,
        });
        const data = await resp.json();
        if (
          data &&
          (data.code === "200" || data.code === 200) &&
          data.data &&
          data.data.url
        ) {
          // 插入为可下载链接
          const url = data.data.url;
          const name = data.data.name || file.name;
          execCommand(
            "insertHTML",
            `<a href="${url}" target="_blank" rel="noopener">${name}</a>`
          );
          ElMessage.success("附件已插入");
        } else {
          ElMessage.error(data?.message || "上传附件失败");
        }
      } catch (err) {
        ElMessage.error("上传附件失败");
      } finally {
        if (fileInputRef.value) fileInputRef.value.value = "";
      }
    };

    // 选择视频后上传
    const onVideoSelected = async (e) => {
      const file = e.target.files && e.target.files[0];
      if (!file) return;
      try {
        const apiConfig = config.getApiConfig();
        const form = new FormData();
        form.append("file", file);
        form.append("type", "video");
        const resp = await fetch(`${apiConfig.baseURL}/api/upload/video`, {
          method: "POST",
          headers: {
            token: localStorage.getItem("adminToken") || "",
          },
          body: form,
        });
        const data = await resp.json();
        if (
          data &&
          (data.code === "200" || data.code === 200) &&
          data.data &&
          data.data.url
        ) {
          const url = data.data.url;
          const videoHtml = `<video src="${url}" controls style="max-width:100%;height:auto"></video>`;
          execCommand("insertHTML", videoHtml);
          ElMessage.success("视频已插入");
        } else {
          ElMessage.error(data?.message || "上传视频失败");
        }
      } catch (err) {
        ElMessage.error("上传视频失败");
      } finally {
        if (videoInputRef.value) videoInputRef.value.value = "";
      }
    };

    // 视频：插入URL
    const insertVideo = () => {
      videoUrl.value = "";
      showVideoUrlDialog.value = true;
    };
    const confirmInsertVideoByUrl = () => {
      const url = (videoUrl.value || "").trim();
      if (!url) return (showVideoUrlDialog.value = false);
      const videoHtml = `<video src="${url}" controls style="max-width:100%;height:auto"></video>`;
      execCommand("insertHTML", videoHtml);
      showVideoUrlDialog.value = false;
    };

    // 应用颜色
    const applyFontColor = (color) => {
      if (!color) return;
      restoreSelection();
      execCommand("foreColor", color);
    };
    const applyBgColor = (color) => {
      if (!color) return;
      restoreSelection();
      // 优先hiliteColor，兼容用backColor
      try {
        execCommand("hiliteColor", color);
      } catch (_) {
        execCommand("backColor", color);
      }
    };

    // 调整选中图片大小
    const resizeSelectedImage = () => {
      const selectedImg = editorRef.value?.querySelector(
        "img.resizable-image.selected"
      );

      if (!selectedImg) {
        ElMessage.warning("请先点击选中一张图片");
        return;
      }

      // 循环切换图片大小
      const currentWidth =
        selectedImg.style.maxWidth || selectedImg.style.width || "400px";
      const sizes = ["200px", "300px", "400px", "500px", "600px", "100%"];
      const currentIndex = sizes.indexOf(currentWidth);
      const nextIndex = (currentIndex + 1) % sizes.length;

      selectedImg.style.maxWidth = sizes[nextIndex];
      selectedImg.style.width = sizes[nextIndex];
      selectedImg.style.height = "auto";

      ElMessage.success(`图片大小已调整为: ${sizes[nextIndex]}`);
      updateModelValue();
    };

    // 插入表格
    const insertTable = () => {
      tableRows.value = 3;
      tableCols.value = 3;
      showTableDialog.value = true;
    };
    const confirmInsertTable = () => {
      const rows = Math.max(1, parseInt(tableRows.value || 1));
      const cols = Math.max(1, parseInt(tableCols.value || 1));
      const table = document.createElement("table");
      table.style.border = "1px solid #ccc";
      table.style.borderCollapse = "collapse";
      table.style.width = "100%";
      for (let i = 0; i < rows; i++) {
        const row = document.createElement("tr");
        for (let j = 0; j < cols; j++) {
          const cell = document.createElement("td");
          cell.style.border = "1px solid #ccc";
          cell.style.padding = "8px";
          cell.innerHTML = "&nbsp;";
          row.appendChild(cell);
        }
        table.appendChild(row);
      }
      execCommand("insertHTML", table.outerHTML);
      showTableDialog.value = false;
    };

    // 清除格式
    const clearFormat = () => {
      execCommand("removeFormat");
    };

    // 撤销
    const undo = () => {
      execCommand("undo");
    };

    // 重做
    const redo = () => {
      execCommand("redo");
    };

    // 处理输入
    const handleInput = () => {
      updateModelValue();
    };

    // 处理键盘事件
    const handleKeydown = (e) => {
      // Ctrl+B 粗体
      if (e.ctrlKey && e.key === "b") {
        e.preventDefault();
        execCommand("bold");
      }
      // Ctrl+I 斜体
      if (e.ctrlKey && e.key === "i") {
        e.preventDefault();
        execCommand("italic");
      }
      // Ctrl+U 下划线
      if (e.ctrlKey && e.key === "u") {
        e.preventDefault();
        execCommand("underline");
      }
    };

    // 处理粘贴
    const handlePaste = (e) => {
      e.preventDefault();
      const text = e.clipboardData.getData("text/plain");
      execCommand("insertText", text);
    };

    // 处理焦点
    const handleFocus = () => {
      isFocused.value = true;
    };

    const handleBlur = () => {
      isFocused.value = false;
      // 移除所有图片的选中状态
      const images = editorRef.value?.querySelectorAll(
        "img.resizable-image.selected"
      );
      images?.forEach((img) => img.classList.remove("selected"));
    };

    // 处理图片点击选中
    const handleImageClick = (e) => {
      if (
        e.target.tagName === "IMG" &&
        e.target.classList.contains("resizable-image")
      ) {
        e.preventDefault();

        // 移除其他图片的选中状态
        const images = editorRef.value?.querySelectorAll(
          "img.resizable-image.selected"
        );
        images?.forEach((img) => img.classList.remove("selected"));

        // 选中当前图片
        e.target.classList.add("selected");

        // 使图片可以通过拖拽调整大小
        makeImageResizable(e.target);
      }
    };

    // 让图片可以拖拽调整大小
    const makeImageResizable = (img) => {
      let isResizing = false;
      let startX, startY, startWidth, startHeight;

      const onMouseDown = (e) => {
        if (e.target !== img) return;
        isResizing = true;
        startX = e.clientX;
        startY = e.clientY;
        startWidth = parseInt(window.getComputedStyle(img).width, 10);
        startHeight = parseInt(window.getComputedStyle(img).height, 10);

        document.addEventListener("mousemove", onMouseMove);
        document.addEventListener("mouseup", onMouseUp);
        e.preventDefault();
      };

      const onMouseMove = (e) => {
        if (!isResizing) return;

        const width = startWidth + (e.clientX - startX);
        const height = startHeight + (e.clientY - startY);

        if (width > 50 && height > 30) {
          img.style.width = width + "px";
          img.style.height = height + "px";
          img.style.maxWidth = width + "px";
        }
      };

      const onMouseUp = () => {
        isResizing = false;
        document.removeEventListener("mousemove", onMouseMove);
        document.removeEventListener("mouseup", onMouseUp);
        updateModelValue();
      };

      img.addEventListener("mousedown", onMouseDown);
    };

    // 更新模型值
    const updateModelValue = () => {
      if (editorRef.value) {
        const content = editorRef.value.innerHTML;
        emit("update:modelValue", content);
        emit("change", content);
      }
    };

    // 监听模型值变化
    watch(
      () => props.modelValue,
      (newValue) => {
        if (editorRef.value && editorRef.value.innerHTML !== newValue) {
          editorRef.value.innerHTML = newValue || "";
        }
      }
    );

    onMounted(() => {
      nextTick(() => {
        initEditor();
      });
      // 跟踪选区变化
      document.addEventListener("selectionchange", () => {
        if (!isFocused.value) return;
        saveSelection();
      });
    });

    return {
      editorRef,
      imageInputRef,
      fileInputRef,
      videoInputRef,
      fontSize,
      fontFamily,
      isFocused,
      execCommand,
      isActive,
      changeFontSize,
      changeFontFamily,
      insertLink,
      confirmInsertLink,
      insertImage,
      confirmInsertImage,
      triggerImageUpload,
      insertVideo,
      triggerVideoUpload,
      triggerFileUpload,
      onImageSelected,
      onFileSelected,
      onVideoSelected,
      resizeSelectedImage,
      insertTable,
      confirmInsertTable,
      clearFormat,
      undo,
      redo,
      handleInput,
      handleKeydown,
      handlePaste,
      handleFocus,
      handleBlur,
      handleImageClick,
      showLinkDialog,
      linkUrl,
      showImageUrlDialog,
      imageUrl,
      showVideoUrlDialog,
      videoUrl,
      showTableDialog,
      tableRows,
      tableCols,
      fontColor,
      bgColor,
      applyFontColor,
      applyBgColor,
    };
  },
};
</script>

<style scoped>
.rich-text-editor {
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  overflow: hidden;
}

.editor-toolbar {
  display: flex;
  align-items: center;
  padding: 8px 12px;
  background: #f5f7fa;
  border-bottom: 1px solid #dcdfe6;
  flex-wrap: wrap;
  gap: 8px;
}

.toolbar-group {
  display: flex;
  align-items: center;
  gap: 4px;
}

.editor-content {
  padding: 12px;
  min-height: 200px;
  outline: none;
  line-height: 1.6;
  font-size: 14px;
  color: #606266;
  background: white;
}

.editor-content:empty:before {
  content: attr(data-placeholder);
  color: #c0c4cc;
  pointer-events: none;
}

.editor-content:focus {
  border-color: #409eff;
}

.editor-content img {
  max-width: 400px;
  height: auto;
  display: inline-block;
  margin: 5px;
  transition: all 0.3s ease;
}

.editor-content img.resizable-image {
  min-width: 100px;
  min-height: 50px;
  cursor: pointer;
  position: relative;
}

.editor-content img.resizable-image:hover {
  border: 2px solid #409eff;
  box-shadow: 0 2px 8px rgba(64, 158, 255, 0.3);
}

.editor-content img.resizable-image:focus,
.editor-content img.resizable-image.selected {
  border: 2px solid #409eff;
  outline: none;
  box-shadow: 0 4px 12px rgba(64, 158, 255, 0.4);
}

.editor-content img.resizable-image.selected::after {
  content: "拖拽调整大小";
  position: absolute;
  top: -25px;
  left: 0;
  background: rgba(64, 158, 255, 0.9);
  color: white;
  font-size: 11px;
  padding: 2px 6px;
  border-radius: 3px;
  white-space: nowrap;
  z-index: 10;
}

.editor-content table {
  border-collapse: collapse;
  width: 100%;
  margin: 10px 0;
}

.editor-content table td {
  border: 1px solid #ccc;
  padding: 8px;
}

.editor-content ul,
.editor-content ol {
  margin: 10px 0;
  padding-left: 20px;
}

.editor-content p {
  margin: 8px 0;
}

.editor-content h1,
.editor-content h2,
.editor-content h3,
.editor-content h4,
.editor-content h5,
.editor-content h6 {
  margin: 16px 0 8px 0;
  font-weight: bold;
}

.editor-content h1 {
  font-size: 24px;
}
.editor-content h2 {
  font-size: 20px;
}
.editor-content h3 {
  font-size: 18px;
}
.editor-content h4 {
  font-size: 16px;
}
.editor-content h5 {
  font-size: 14px;
}
.editor-content h6 {
  font-size: 12px;
}

@media (max-width: 768px) {
  .editor-toolbar {
    flex-direction: column;
    align-items: flex-start;
  }

  .toolbar-group {
    margin-bottom: 8px;
  }
}
</style>
